package com.example.librarymanagement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.librarymanagement.dao.MenuMapper;
import com.example.librarymanagement.dao.UserMapper;
import com.example.librarymanagement.dto.user.UserListDto;
import com.example.librarymanagement.entity.Menu;
import com.example.librarymanagement.entity.Role;
import com.example.librarymanagement.entity.User;
import com.example.librarymanagement.service.IMenuService;
import com.example.librarymanagement.service.IRoleService;
import com.example.librarymanagement.service.IUserService;
import com.example.librarymanagement.util.RedisUtil;
import com.example.librarymanagement.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhb
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private IRoleService roleService;

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private IMenuService menuService;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public IPage<UserVo> getUserList(UserListDto userListDto) {
        IPage<UserVo> page = new Page<>(userListDto.getCurrent(), userListDto.getSize());

        return baseMapper.getUserList(page, userListDto);
    }

    @Override
    public User getUserByUsername(String username) {
        return getOne(new QueryWrapper<User>().eq("username", username));
    }

    @Override
    public String getUserAuthorityInfo(Integer userId) {
        User user = getById(userId);

        StringBuffer authority = new StringBuffer();
        if (redisUtil.hasKey("GrantedAuthority:" + user.getUsername())) {
            authority.append((String) redisUtil.get("GrantedAuthority:" + user.getUsername()));
        } else {
            List<Role> roles = roleService.list(new QueryWrapper<Role>().inSql("id", "select role_id from t_user_role where user_id = " + userId));
            if (roles.size() > 0) {
                authority.append(
                        roles.stream()
                                .map(role -> "ROLE_" + role.getCode()).collect(Collectors.joining(",")));
                authority.append(",");
            }
            List<Integer> menuIds = menuMapper.getNavMenuIds(userId);
            if (menuIds.size() > 0) {
                List<Menu> menus = menuService.listByIds(menuIds);
                authority.append(
                        menus.stream()
                                .map(Menu::getPerms).collect(Collectors.joining(",")));
            }
            log.info("用户ID - {} ---拥有的权限：{}", userId, authority);
            redisUtil.set("GrantedAuthority:" + user.getUsername(), authority.toString(), 60 * 60);
        }
        return authority.toString();
    }

    @Override
    public void clearUserAuthorityInfo(String username) {
        redisUtil.del("GrantedAuthority:" + username);
    }

    @Override
    public void clearUserAuthorityInfoByRoleId(Integer roleId) {
        List<User> users = this.list(new QueryWrapper<User>()
                .inSql("id", "select user_id from t_user_role where role_id = " + roleId));
        users.forEach(user -> {
            this.clearUserAuthorityInfo(user.getUsername());
        });
    }

    @Override
    public void clearUserAuthorityInfoByMenuId(Integer menuId) {
        List<User> users = baseMapper.listByMenuId(menuId);
        users.forEach(user -> {
            this.clearUserAuthorityInfo(user.getUsername());
        });
    }

}
